package com.zsj.channel;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.ImmutableMap;
import com.zsj.config.ConfigBean;
import com.zsj.config.SpddMapping;
import com.zsj.entity.*;
import com.zsj.enums.*;
import com.zsj.exception.BusinessException;
import com.zsj.mysql.entity.AppProductPrice;
import com.zsj.mysql.entity.DyMobileRecharge;
import com.zsj.mysql.service.IAppProductPriceService;
import com.zsj.mysql.service.IDyMobileRechargeService;
import com.zsj.service.DiscountService;
import com.zsj.service.NotifyDyService;
import com.zsj.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.http.conn.ConnectTimeoutException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.SocketTimeoutException;
import java.util.*;

/**
 * @Description:
 * @Author:
 * @Date:
 */
@Slf4j
@Service
public class SpddService {

    @Autowired
    private ConfigBean configBean;

    @Autowired
    private SpddMapping spddMapping;

    @Autowired
    private IDyMobileRechargeService mobileRechargeService;

    @Autowired
    private NotifyDyService notifyDyService;

    @Autowired
    private IAppProductPriceService appProductPriceService;

    @Autowired
    private DiscountService discountService;

    private static final Map<String, String> CARRIER_MAPPER = ImmutableMap.<String, String>builder()
            .put("CT", "11")
            .put("CU", "10")
            .put("CM", "9")
            .put("BN", "12")
            .build();


    public static final Map<String, String> PACKAGEID_MAPPER = ImmutableMap.<String, String>builder()
            .put("CT", "DXHF")
            .put("CU", "LTHF")
            .put("CM", "YDHF")
            .build();

    // todo 确定对方的枚举值
    private static final Map<String, String> OPERATOR_MAPPER = ImmutableMap.<String, String>builder()
            .put("移动", "CM")
            .put("联通", "CU")
            .put("电信", "CT")
            .put("BROAD_NET", "BN")
            .build();

    // todo 错误码映射
    private static final Map<String, String> CHARGE_ORDER_STATUS_MAPPER = ImmutableMap.<String, String>builder()
            .put("00", "2")
            .put("01", "1")
            .put("02", "1")
            .put("03", "2")
            .put("04", "1")
            .put("05", "1")
            .put("06", "2")
            .put("07", "1")
            .put("08", "1")
            .put("09", "1")
            .put("10", "2")
            .put("11", "1")
            .put("12", "1")
            .put("13", "1")
            .put("14", "1")
            .put("30", "1")
            .put("205", "1")
            .put("301", "1")
            .put("306", "1")
            .put("99", "2")
            .build();

    /**
     * 1－待发 2－已发 3- 重发中 4－失败 6—成功 10-订单不存在
     */
    private static final Map<String, String> QUERY_ORDER_STATUS_MAPPER = ImmutableMap.<String, String>builder()
            .put("1", "2")
            .put("2", "2")
            .put("3", "2")
            .put("4", "1")
            .put("6", "0")
            .put("10", "1") // 订单不存在，返回失败
            .build();

    /**
     * 00-成功，99-失败， 其他- 不处理
     */
    private static final Map<String, Integer> NOTIFY_ORDER_STATUS_MAPPER = ImmutableMap.<String, Integer>builder()
            .put("00", 0)
            .put("99", 1)
            .build();

    private static final Map<String, Integer> PRODUCT_STATUS_MAPPER = ImmutableMap.<String, Integer>builder()
            .put("normal", 1)
            .put("maintenance", 0)
            .build();


    public void orderRecharge(DyMobileRecharge entity, RechargeResponse response) {
        log.info("请求SPDD订单受理接口");
        try {
            String str = spddMapping.getMapping().get(entity.getAppId());
            String[] arr = StringUtils.split(str, "@@@", -1);
            String url = configBean.getHost() + "/mk/phone/add_minutes/new_order";
            String timestamp = DateUtil.getSpddTimestamp();
            String seqNo = IDGenerator.getSpddSeqNo();
            String appId = arr[0];
            JSONObject reqHeader = new JSONObject();
            reqHeader.put("version", "v1.0");
            reqHeader.put("timestamp", timestamp);
            reqHeader.put("seqNo", seqNo);
            reqHeader.put("appId", appId);
            reqHeader.put("secertKey", Md5Util.createMD5ByStr(timestamp + seqNo + appId + arr[1]));

            JSONObject content = new JSONObject();
            content.put("phoneNo", entity.getMobile());
            content.put("packageId", PACKAGEID_MAPPER.get(entity.getCarrierCode()) +
                    Integer.valueOf(entity.getProductDenomination()) / 100);
            // content.put("custOrderId", MDC.get("selfUid"));
            content.put("custOrderId", entity.getChannelChargeNo());

            // 地区
            content.put("areaCode", StrUtil.blankToDefault(StrUtil.subWithLength(entity.getAdCode(), 0, 2), ""));

            // 运营商
            content.put("operator", entity.getCarrierCode());

            // 分
            content.put("price", entity.getProductDenomination());
            content.put("sign", Md5Util.createMD5ByStr(arr[1] + entity.getMobile()
                    + content.get("packageId") + content.get("custOrderId")));
            JSONObject reqBody = new JSONObject();
            reqBody.put("content", content);

            JSONObject reqJson = new JSONObject();
            reqJson.put("reqHeader", reqHeader);
            reqJson.put("reqBody", reqBody);

            Map<String, String> header = new HashMap<>(2);
            header.put("Content-Type", "application/json");

            log.info("请求SPDD的订单受理接口, url={}, 参数={}", url, reqJson.toJSONString());
            HttpReturnMessage httpReturnMessage = HttpUtil.doPost(url, reqJson.toJSONString(), header, 1000,
                    configBean.getReadTimeout());
            if (httpReturnMessage.getStatusCode() != HttpStatus.SC_OK) {
                log.info("http返回码{}非200，作为处理中", httpReturnMessage.getStatusCode());
                response.setOrderStatus(OrderStatusEnum.PROCESSING.getCode());
                if (httpReturnMessage.getStatusCode() == HttpStatus.SC_NOT_FOUND) {
                    // 404标记为需要重发。其中lastReorderTime赋值为null，在sql中根据lastReorderTime是否为空判断是否更新重发次数和重发时间
                    log.info("下单接口返回404，标记为待重发");
                    mobileRechargeService.updateReorder(String.valueOf(entity.getTxnDate()).substring(0, 6), ReorderStatusEnum.WAIT.getCode(), null, entity.getChargeNo());
                }
                return;
            }
            log.info("请求SPDD订单受理接口响应为：{}", httpReturnMessage.getResult());
            JSONObject spddResponse = JSONObject.parseObject(httpReturnMessage.getResult());
            JSONObject respBody = Optional.ofNullable(spddResponse.getJSONObject("respBody")).orElse(new JSONObject());
            JSONObject resp = Optional.ofNullable(respBody.getJSONObject("resp")).orElse(new JSONObject());
            JSONObject respContent = Optional.ofNullable(respBody.getJSONObject("content")).orElse(new JSONObject());
            // 返回码
            String respCode = resp.getString("code");
            // spdd订单号
            String orderId = respContent.getString("orderId");
            response.setSupplierOrderNo(orderId);
            response.setOrderStatus(CHARGE_ORDER_STATUS_MAPPER.getOrDefault(respCode,
                    OrderStatusEnum.PROCESSING.getCode()));
            // 订单终态时赋值完成时间
            if (OrderStatusEnum.isFinal(response.getOrderStatus())) {
                response.setFinishTime(DateUtil.getCurrentDateTime());
            }
            // 失败时dy要求code非0000，所以要进行错误码映射
            if (OrderStatusEnum.FAILED.getCode().equals(response.getOrderStatus())) {
                log.info("订单受理失败，进行错误码映射");
                // todo 错误码映射
                switch (respCode) {
                    // 手机号码格式错误
                    case "05":
                        // 超出运营商风险控制要求
                    case "12":
                        throw new BusinessException(ErrorCodeEnum.MOBILE_NOT_SUPPORT);
                        // 省份维护 或者 超出运营商风险控制要求
                    case "30":
                        // 产品维护
                    case "205":
                        throw new BusinessException(ErrorCodeEnum.PRODUCT_MAINTENANCE);
                        // 话费包ID错误
                    case "04":
                        throw new BusinessException(ErrorCodeEnum.PRODUCT_NOT_CONFIGURED);
                    default:
                        throw new BusinessException(ErrorCodeEnum.SUPPLIER_FAIL);
                }
            }
        } catch (BusinessException be) {
            throw be;
        } catch (ConnectTimeoutException cte) {
            log.info("http链接超时,作为失败处理");
            response.setOrderStatus(OrderStatusEnum.FAILED.getCode());
            response.setFinishTime(DateUtil.getCurrentDateTime());
            throw new BusinessException(ErrorCodeEnum.SUPPLIER_FAIL);
        } catch (SocketTimeoutException se) {
            log.error("请求SPDD订单受理接口读超时", se);
            response.setOrderStatus(OrderStatusEnum.PROCESSING.getCode());
        } catch (Exception e) {
            log.error("请求SPDD订单受理接口异常", e);
            response.setOrderStatus(OrderStatusEnum.PROCESSING.getCode());
            // 非读超时的其他异常，标记为需要重发。其中lastReorderTime赋值为null，在sql中根据lastReorderTime是否为空判断是否更新重发次数和重发时间
            mobileRechargeService.updateReorder(String.valueOf(entity.getTxnDate()).substring(0, 6), ReorderStatusEnum.WAIT.getCode(), null, entity.getChargeNo());
        }
    }

    public void orderQuery(DyMobileRecharge record, RechargeResponse response) {
        log.info("请求SPDD订单查询接口，自己的订单号:{}", record.getChannelChargeNo());
        try {
            String str = spddMapping.getMapping().get(record.getAppId());
            String[] arr = StringUtils.split(str, "@@@", -1);
            String url = configBean.getHost() + "/go/phone/add_minutes/get_order";
            String timestamp = DateUtil.getSpddTimestamp();
            String seqNo = IDGenerator.getSpddSeqNo();
            String appId = arr[0];
            JSONObject reqHeader = new JSONObject();
            reqHeader.put("version", "v1.0");
            reqHeader.put("timestamp", timestamp);
            reqHeader.put("seqNo", seqNo);
            reqHeader.put("appId", appId);
            reqHeader.put("secertKey", Md5Util.createMD5ByStr(timestamp + seqNo + appId + arr[1]));

            JSONObject content = new JSONObject();
            content.put("custOrderId", record.getChannelChargeNo());
            content.put("sign", Md5Util.createMD5ByStr(arr[1] + record.getChannelChargeNo()));
            JSONObject reqBody = new JSONObject();
            reqBody.put("content", content);

            JSONObject reqJson = new JSONObject();
            reqJson.put("reqHeader", reqHeader);
            reqJson.put("reqBody", reqBody);

            Map<String, String> header = new HashMap<>(2);
            header.put("Content-Type", "application/json");

            log.info("请求SPDD的订单查询接口的参数为：{}", reqJson.toJSONString());
            HttpReturnMessage httpReturnMessage = HttpUtil.doPost(url, reqJson.toJSONString(), header, 1000,
                    configBean.getReadTimeout());
            if (httpReturnMessage.getStatusCode() != HttpStatus.SC_OK) {
                log.info("http返回码{}非200，作为处理中", httpReturnMessage.getStatusCode());
                response.setOrderStatus(OrderStatusEnum.PROCESSING.getCode());
                return;
            }
            log.info("请求SPDD订单查询接口响应为：{}", httpReturnMessage.getResult());
            JSONObject spddResponse = JSONObject.parseObject(httpReturnMessage.getResult());
            JSONObject respBody = Optional.ofNullable(spddResponse.getJSONObject("respBody")).orElse(new JSONObject());
            JSONObject respContent = Optional.ofNullable(respBody.getJSONObject("content")).orElse(new JSONObject());

            // 读取返回码
            JSONObject resp = Optional.ofNullable(respBody.getJSONObject("resp")).orElse(new JSONObject());
            String respCode = resp.getString("code");

            if ("10".equals(respCode)) { // 订单不存在
                response.setOrderStatus(QUERY_ORDER_STATUS_MAPPER.getOrDefault(respCode,
                        OrderStatusEnum.PROCESSING.getCode()));
            } else { // 其他情况，根据 status 状态判断
                String orderStatus = respContent.getString("status");
                response.setOrderStatus(QUERY_ORDER_STATUS_MAPPER.getOrDefault(orderStatus,
                        OrderStatusEnum.PROCESSING.getCode()));
            }
            // 毫
            String price = respContent.getString("price");
            // 供应商结算金额，毫
            response.setSupplierContractPrice(price);
            // 订单终态时赋值完成时间
            if (OrderStatusEnum.isFinal(response.getOrderStatus())) {
                String addEndTime = respContent.getString("addEndTime");
                String finishTime = DateUtil.convertDateFormat(addEndTime);
                if (null == finishTime) {
                    log.info("addEndTime转换失败，取当前时间");
                    finishTime = DateUtil.getCurrentDateTime();
                }
                response.setFinishTime(finishTime);
            }
            response.setSupplierOrderNo(respContent.getString("orderId"));

            // 失败时dy要求code非0000，所以要进行错误码映射
            if (OrderStatusEnum.FAILED.getCode().equals(response.getOrderStatus())) {
                log.info("订单查询原交易失败，进行错误码映射");
                // JSONObject resp = Optional.ofNullable(respBody.getJSONObject("resp")).orElse(new JSONObject());
                // 返回码
                // String respCode = resp.getString("code");
                // todo 错误码映射
                switch (respCode) {
                    // 手机号码格式错误
                    case "05":
                        // 超出运营商风险控制要求
                    case "10":
                        // 订单不存在
                        throw new BusinessException(ErrorCodeEnum.ORDER_NOT_EXIST);
                    case "12":
                        throw new BusinessException(ErrorCodeEnum.MOBILE_NOT_SUPPORT);
                        // 省份维护 或者 超出运营商风险控制要求
                    case "30":
                        // 产品维护
                    case "205":
                        throw new BusinessException(ErrorCodeEnum.PRODUCT_MAINTENANCE);
                        // 话费包ID错误
                    case "04":
                        throw new BusinessException(ErrorCodeEnum.PRODUCT_NOT_CONFIGURED);
                    default:
                        throw new BusinessException(ErrorCodeEnum.SUPPLIER_FAIL);
                }
            }
        } catch (BusinessException be) {
            throw be;
        } catch (Exception e) {
            log.error("请求SPDD订单查询接口异常", e);
            response.setOrderStatus(OrderStatusEnum.PROCESSING.getCode());
        }
    }

    public void dealNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            StringBuilder sb = new StringBuilder();
            String line;
            try (BufferedReader reader = request.getReader()) {
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            }
            String message = sb.toString();
            log.info("回调通知报文:{}", message);
            JSONObject json = JSONObject.parseObject(message);
            JSONObject reqBody = Optional.ofNullable(json.getJSONObject("reqBody")).orElse(new JSONObject());
            JSONObject content = Optional.ofNullable(reqBody.getJSONObject("content")).orElse(new JSONObject());
            String orderNo = content.getString("custOrderId");
            QueryWrapper<DyMobileRecharge> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("channel_charge_no", orderNo);
            DyMobileRecharge record = mobileRechargeService.getOne(queryWrapper);
            if (ObjectUtils.isEmpty(record)) {
                log.info("当前月份表未查得，查询上月分表");
                // 默认查询当月的，如果下单是在月末最后一天，查询是在下个月，则此时查不到元交易，需要在上一个月的分表中查询
                record = mobileRechargeService.getBySelfOrderNo(DateUtil.getLastMonth(), orderNo);
                if (ObjectUtils.isEmpty(record)) {
                    log.info("根据订单号{}未查询到订单", orderNo);
                    throw new BusinessException(ErrorCodeEnum.ORDER_NOT_EXIST);
                }
            }
            // todo 取code字段？
            Integer spddOrderStatus = NOTIFY_ORDER_STATUS_MAPPER.get(content.getString("code"));
            log.info("回调报文中映射后订单状态为:{}", spddOrderStatus);
            // 本地成功，spdd为失败，则更新为返销
            boolean reExchange = OrderStatusEnum.SUCCESS.getCode().equals(record.getOrderStatus() + "")
                    && OrderStatusEnum.FAILED.getCode().equals(spddOrderStatus + "");
            // 非返销的场景时本地已经终态则不处理通知
            if (OrderStatusEnum.isFinal(record.getOrderStatus() + "")
                    && !reExchange) {
                log.info("订单{}已为终态，且不满足返销，直接返回", orderNo);
                return;
            }
            log.info("订单{}非终态，或者本地成功但通道失败处理为返销，开始更新订单", orderNo);
            record.setOrderStatus(spddOrderStatus);
            if (reExchange) {
                record.setOrderStatus(Integer.valueOf(OrderStatusEnum.REEXCHANGE.getCode()));
            }
            if (!OrderStatusEnum.isFinal(record.getOrderStatus() + "")) {
                log.info("订单状态{}非终态，不处理", request.getParameter("orderStatus"));
                return;
            }
            record.setSupplierOrderNo(content.getString("orderId"));
            // 毫
            String price = content.getString("price");
            // 毫
            record.setSupplierContractPrice(price);
            String addEndTime = content.getString("addEndTime");
            String finishTime = DateUtil.convertDateFormat(addEndTime);
            if (null == finishTime) {
                log.info("addEndTime转换失败，取当前时间");
                finishTime = DateUtil.getCurrentDateTime();
            }
            record.setFinishTime(finishTime);
            // 成功时赋值成功时间
            if (OrderStatusEnum.SUCCESS.getCode().equals(record.getOrderStatus() + "")) {
                record.setSuccessTime(finishTime);
                record.setReturnCode(ErrorCodeEnum.SUCCESS.getCode());
                record.setReturnMessage(ErrorCodeEnum.SUCCESS.getMsg());
            } else if (OrderStatusEnum.REEXCHANGE.getCode().equals(record.getOrderStatus() + "")) {
                record.setReturnCode(ErrorCodeEnum.SUCCESS.getCode());
                record.setReturnMessage(ErrorCodeEnum.SUCCESS.getMsg());
            } else {
                // todo 没有错误码，按照供应商失败？
                ErrorCodeEnum errorCodeEnum = ErrorCodeEnum.SUPPLIER_FAIL;
                record.setReturnCode(errorCodeEnum.getCode());
                record.setReturnMessage(errorCodeEnum.getMsg());
            }
            record.setFinishDate(Integer.valueOf(finishTime.substring(0, 10).replaceAll("-", "")));
            String month = String.valueOf(record.getTxnDate()).substring(0, 6);
            mobileRechargeService.updateFinal(month, record);
            try (PrintWriter out = response.getWriter()) {
                String data = "{\"respBody\":{\"resp\":{\"code\":\"00\",\"msg\":\"ok\"}}}";
                out.write(data);
                out.flush();
            } catch (IOException e) {
                log.error("回调报文处理后写入响应失败", e);
            }
            notifyDyService.notifyDy(record);
        } catch (Exception e) {
            log.error("处理回调通知异常", e);
        }
    }

    public ProductQueryResponse productQuery(ProductQueryRequest request) {
        log.info("请求SPDD订商品状态查询接口");
        ProductQueryResponse response = new ProductQueryResponse();
        try {
            String str = spddMapping.getMapping().get(request.getAppId());
            String[] arr = StringUtils.split(str, "@@@", -1);
            String url = configBean.getHost() + "/mt/phone/add_minutes/maintain/list";
            String timestamp = DateUtil.getSpddTimestamp();
            String seqNo = IDGenerator.getSpddSeqNo();
            String appId = arr[0];
            JSONObject reqHeader = new JSONObject();
            reqHeader.put("version", "v1.0");
            reqHeader.put("timestamp", timestamp);
            reqHeader.put("seqNo", seqNo);
            reqHeader.put("appId", appId);
            reqHeader.put("secertKey", Md5Util.createMD5ByStr(timestamp + seqNo + appId + arr[1]));

            JSONObject content = new JSONObject();
            long bodyTimestamp = System.currentTimeMillis();
            content.put("timestamp", bodyTimestamp);
            content.put("sign", Md5Util.createMD5ByStr(arr[1] + bodyTimestamp));
            JSONObject reqBody = new JSONObject();
            reqBody.put("content", content);

            JSONObject reqJson = new JSONObject();
            reqJson.put("reqHeader", reqHeader);
            reqJson.put("reqBody", reqBody);

            Map<String, String> header = new HashMap<>(2);
            header.put("Content-Type", "application/json");

            log.info("请求SPDD的产品维护接口的参数为：{}", reqJson.toJSONString());
            HttpReturnMessage httpReturnMessage = HttpUtil.doPost(url, reqJson.toJSONString(), header, 1000,
                    configBean.getReadTimeout());
            if (httpReturnMessage.getStatusCode() != HttpStatus.SC_OK) {
                log.info("http返回码{}非200，作为失败", httpReturnMessage.getStatusCode());
                throw new BusinessException(ErrorCodeEnum.SUPPLIER_FAIL);
            }
            log.info("请求SPDD商品状态查询接口响应为：{}", httpReturnMessage.getResult());
            JSONObject spddResponse = JSONObject.parseObject(httpReturnMessage.getResult());
            JSONObject respBody = Optional.ofNullable(spddResponse.getJSONObject("respBody")).orElse(new JSONObject());
            JSONArray respContent = Optional.ofNullable(respBody.getJSONArray("content")).orElse(new JSONArray());

            // todo 需要先要到SPDD全量支持产品信息并入库
            log.info("开始查询本地数据库商户{}的产品列表", request.getAppId());
            QueryWrapper<AppProductPrice> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("app_id", request.getAppId());
            List<AppProductPrice> dbList = appProductPriceService.list(queryWrapper);
            List<MaintainInfo> list = new ArrayList<>();
            // 防重用的，保证运营商、产品编码、省份三个字段作为唯一索引
            Map<String, MaintainInfo> map = new HashMap<>(8);
            // 先以数据库为准，全部变为上架
            for (AppProductPrice appProductPrice : dbList) {
                // map的key，其实是运营商、产品编码、省份三个维度一起作为key，借助map用于防重
                String key = appProductPrice.getCarrierCode() + "-" + appProductPrice.getProductDenomination();
                // 如果数据库配置了某运营商某产品为ALL即全国，则不再考虑数据库中该运营商该产品具体省份的记录，而是直接根据省份枚举将每一个省份都作为一条记录插入到list中。
                // 也就是将该运营商该产品具体省份的记录先从list中移除，再遍历省份枚举依次插入一条记录。
                if ("ALL".equals(appProductPrice.getAdCode())) {
                    // 移除该运营商该产品具体省份的记录
                    list.removeIf(info -> info.getCarrierCode().equals(appProductPrice.getCarrierCode())
                            && info.getProductDenomination().equals(appProductPrice.getProductDenomination()));
                    // 将所有省份都插入一条记录
                    for (AdCodeEnum adCodeEnum : AdCodeEnum.values()) {
                        MaintainInfo info = new MaintainInfo();
                        info.setCarrierCode(appProductPrice.getCarrierCode());
                        info.setProductDenomination(appProductPrice.getProductDenomination());
                        info.setAdCode(adCodeEnum.getCode());
                        info.setStatus(1);
                        info.setBizType("FEE");
                        info.setSubBizType("FEE");
                        list.add(info);
                        map.put(key + "-" + adCodeEnum.getCode(), info);
                    }
                } else {
                    // 不是"全国"的记录，先直接插入到list2中，但要判断该运营商该产品该省份是不是已经被插入过(可能在处理"全国"的那条记录时已经插入过)
                    if (!map.containsKey(key + "-" + appProductPrice.getAdCode())) {
                        MaintainInfo info = new MaintainInfo();
                        info.setCarrierCode(appProductPrice.getCarrierCode());
                        info.setProductDenomination(appProductPrice.getProductDenomination());
                        info.setAdCode(appProductPrice.getAdCode());
                        info.setStatus(1);
                        info.setBizType("FEE");
                        info.setSubBizType("FEE");
                        list.add(info);
                        map.put(key + "-" + appProductPrice.getAdCode(), info);
                    }
                }
            }

            // 判断spdd产品维护情况
            if (respContent.isEmpty()) {
                log.info("没有维护，以本地数据库中为准");
            } else {
                log.info("SPDD产品存在维护情况，需要覆盖本地产品维护信息");
                // todo 是否需要更新本地库？不用，见下一个todo说明
                for (int i = 0; i < respContent.size(); i++) {
                    JSONObject maintenance = respContent.getJSONObject(i);
                    String province = maintenance.getString("province");
                    String carrierCode = OPERATOR_MAPPER.get(maintenance.getString("operator"));
                    // 金额列表，元
                    JSONArray priceList = maintenance.getJSONArray("facePrice");
                    // 遍历当前运营商下所有产品
                    for (int j = 0; j < priceList.size(); j++) {
                        // 元转分
                        String price = MoneyUtil.yuanToFen(priceList.getString(j));
                        // 全国的，则将所有省份该运营商该产品都下架
                        if ("全国".equals(province)) {
                            for (AdCodeEnum adCodeEnum : AdCodeEnum.values()) {
                                String adCode = adCodeEnum.getCode();
                                String key = carrierCode + "-" + price + "-" + adCode;
                                // spdd下架，且我们本地数据库中有的，则更新状态为下架    todo spdd有但我们没有的，现在就过滤掉，要不要记录下来新增到表里以及返回给dy？但是记录到表里折扣怎么取？所以还是人工维护吧？而且这里是下架，本来也是不可用，多就多了，所以不用维护进去
                                if (map.containsKey(key)) {
                                    MaintainInfo info = map.get(key);
                                    info.setStatus(0);
                                } else {
                                    log.info("carrierCode[{}]price[{}]adCode[{}]在SPDD中已下架，但本系统数据库中无该记录", carrierCode, price, adCode);
                                }
                            }
                        } else {
                            String adCode = AdCodeEnum.findByName(province).getCode();
                            String key = carrierCode + "-" + price + "-" + adCode;
                            // spdd下架，且我们本地数据库中有的，则更新状态为下架    todo spdd有但我们没有的，现在就过滤掉，要不要记录下来新增到表里以及返回给dy？但是记录到表里折扣怎么取？所以还是人工维护吧？而且这里是下架，本来也是不可用，多就多了，所以不用维护进去
                            if (map.containsKey(key)) {
                                MaintainInfo info = map.get(key);
                                info.setStatus(0);
                            } else {
                                log.info("carrierCode[{}]price[{}]adCode[{}]在SPDD中已下架，但本系统数据库中无该记录", carrierCode, price, adCode);
                            }
                        }
                    }
                }
                // 对SPDD存在维护信息时，我们是更新了map中MaintainInfo对象的状态，所以需要将map中对象放到list中返回给dy
                list = new ArrayList<>(map.values());
            }
            response.setMaintainInfo(list);
        } catch (Exception e) {
            log.error("请求SPDD商品状态查询接口异常", e);
            throw new BusinessException(ErrorCodeEnum.SUPPLIER_FAIL);
        }
        return response;
    }

    /**
     * 返回所有渠道，所有产品都维护的数据
     */
    public ProductQueryResponse productMaintenanceAll() {
        ProductQueryResponse response = new ProductQueryResponse();
        List<MaintainInfo> list = new ArrayList<>();

        List<String> denominationList = Arrays.asList("100", "200", "300", "400", "500", "600", "700", "800",
                "900", "1000", "2000", "3000", "5000", "10000", "20000", "30000", "50000");
        for (CarrierCodeEnum carrier : CarrierCodeEnum.values()) {
            for (AdCodeEnum area : AdCodeEnum.values()) {
                denominationList.forEach(denomination -> {
                    MaintainInfo info = new MaintainInfo();
                    info.setCarrierCode(carrier.getCode());
                    info.setAdCode(area.getCode());
                    info.setProductDenomination(denomination);
                    info.setStatus(0); // 已维护
                    info.setBizType("FEE");
                    info.setSubBizType("FEE");
                    list.add(info);
                });
            }
        }
        response.setMaintainInfo(list);

        return response;
    }
}
